package com.logic.landseaserver.service.impl;

import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.logic.common.exception.BusinessException;
import com.logic.common.security.SecurityUtils;
import com.logic.common.util.QueryUtil;
import com.logic.landseaserver.common.LandseaErrorMessageEnum;
import com.logic.landseaserver.common.exception.LandseaBusinessException;
import com.logic.landseaserver.domain.Check;
import com.logic.landseaserver.domain.Issue;
import com.logic.landseaserver.persistence.read.CheckReadMapper;
import com.logic.landseaserver.persistence.write.CheckWriteMapper;
import com.logic.landseaserver.service.ICheckService;
import com.logic.landseaserver.service.IIssueService;
import com.logic.landseaserver.ws.ContractRest;
import com.logic.landseaserver.ws.dto.CheckDTO;

@Service
public class CheckServiceImpl implements ICheckService {

	private static final Logger logger = LoggerFactory.getLogger(CheckServiceImpl.class);

	@Autowired
	private CheckReadMapper checkReadMapper;

	@Autowired
	private CheckWriteMapper checkWriteMapper;

	@Autowired
	private IIssueService issueServiceImpl;




	@Override
	public void delete(String arg0) throws BusinessException {
	    String[] idArr = arg0.split(",");
	    for (String id : idArr) {
	      Integer checkId = Integer.valueOf(id);
	      Check check = (Check) this.get(checkId);
	      Boolean pass = this.validateForDelete(check);
	      if (pass) {
	    	  check.updateCommonInfo(SecurityUtils.getCurrentLogin().getUserId());
	    	  checkWriteMapper.deleteByPrimaryKey(check);
	    	  List<Issue> issues = issueServiceImpl.getByCheckId(checkId);
	    	  if (issues != null) {
		    	  StringBuffer issueIds = new StringBuffer();
	    		  for (Issue issue : issues) {
	    			  Integer issueId = issue.getId();
	    			  issueIds.append(issueId).append(",");
	    			  checkWriteMapper.deleteCheckIssue(checkId, issueId);
	    		  }
	    		  issueServiceImpl.delete(issueIds.toString());
	    	  }
	      }
	    }

	}

	@Override
	public Object get(Integer arg0) throws BusinessException {
		return checkReadMapper.selectByPrimaryKey(arg0);
	}

	@Override
	public int insert(Object arg0) throws BusinessException {
		Integer id = -1;
		Boolean pass = this.validateForInsert(arg0);
		if (pass) {
			Check check = (Check) arg0;
			check.updateCommonInfo(SecurityUtils.getCurrentLogin().getUserId());
			checkWriteMapper.insertSelective(check);
			id = check.getId();
		}
		return id;
	}

	@Override
	public List<?> query(QueryUtil arg0) {
		return checkReadMapper.getCheckList(arg0);
	}

	@Override
	public void update(Object arg0) throws BusinessException {
		Boolean pass = this.validateForUpdate(arg0);
		if (pass) {
			Check check = (Check) arg0;
			check.updateCommonInfo(SecurityUtils.getCurrentLogin().getUserId());
			check.setCreatedBy(null);
			check.setCreatedDtm(null);
			checkWriteMapper.updateByPrimaryKeySelective(check);
		}

	}

	@Override
	public Boolean validate(Object arg0) throws BusinessException {
		Boolean pass = true;
		if (arg0 == null) {
			throw new LandseaBusinessException(LandseaErrorMessageEnum.Check_Insert_Or_Update_Empty_Object);
		}
		if (!(arg0 instanceof Check)) {
			throw new LandseaBusinessException(LandseaErrorMessageEnum.Check_Insert_Or_Update_Type);
		}
		Check check = (Check) arg0;
		if (check.getTemplate() != null && check.getTemplate()) {
			Check nameCheck = checkReadMapper.selectByName(check.getName());
			if (nameCheck != null && !nameCheck.getId().equals(check.getId())) {
				throw new LandseaBusinessException(LandseaErrorMessageEnum.Check_Insert_Or_Update_Name_Repeat);
			}
		}
		return pass;
	}

	@Override
	public Boolean validateForDelete(Object arg0) throws BusinessException {
		return true;
	}

	@Override
	public Boolean validateForInsert(Object arg0) throws BusinessException {
		Boolean pass = false;
		pass = this.validate(arg0);
		Check check = (Check)arg0;
		if (check.getId() != null) {
			throw new LandseaBusinessException(LandseaErrorMessageEnum.Check_CreateCheck_Empty_ID);
		}
		if (StringUtils.isBlank(check.getName())) {
			throw new LandseaBusinessException(LandseaErrorMessageEnum.Check_CreateCheck_Empty_Check_Name);
		}
		if (StringUtils.isBlank(check.getSerialNum())) {
			throw new LandseaBusinessException(LandseaErrorMessageEnum.Check_CreateCheck_Empty_Check_Number);
		}
		if (StringUtils.isBlank(check.getDescription())) {
			throw new LandseaBusinessException(LandseaErrorMessageEnum.Check_CreateCheck_Empty_Check_Description);
		}
		return pass;
	}

	@Override
	public Boolean validateForUpdate(Object arg0) throws BusinessException {
		Boolean pass = false;
		pass = this.validate(arg0);
		Check check = (Check)arg0;
		if (check.getId() == null) {
			throw new LandseaBusinessException(LandseaErrorMessageEnum.Check_UpdateCheck_Empty_Check_ID);
		}
		return pass;
	}

	@Override
	public CheckDTO getDTO(Integer id) throws BusinessException {
		return checkReadMapper.selectDTOByPrimaryKey(id);
	}

	@Override
	public List<CheckDTO> queryDTO(QueryUtil queryUtil) {
		List<CheckDTO> checkDTOList = checkReadMapper.getCheckDTOList(queryUtil);
		this.setIssueNum(checkDTOList);
		return checkDTOList;
	}

	private void setIssueNum(List<CheckDTO> checkDTOList) {
		for (CheckDTO checkDTO : checkDTOList) {
			checkDTO.setIssueNum(issueServiceImpl.countByCheckId(checkDTO.getId()));
		}
	}

	@Override
	public Issue addIssue(Integer checkId, Integer issueId) throws BusinessException {
		Issue issue = issueServiceImpl.copyFromTemplate(issueId);
		checkWriteMapper.insertCheckIssue(checkId, issue.getId());
		return issue;
	}

	@Override
	public Issue addIssue(Integer checkId, Issue issue) throws BusinessException {
		//whether put in storage
		if (issue.getTemplate()) {
			issueServiceImpl.add2Template(issue);
		}
		issue.setId(null);
		issue.setTemplate(false);
		issueServiceImpl.insert(issue);
		Integer issueId = issue.getId();
		checkWriteMapper.insertCheckIssue(checkId, issueId);
		return issue;
	}

	@Override
	public void removeIssue(Integer checkId, Integer issueId) {
		try {
			issueServiceImpl.delete(String.valueOf(issueId));
			checkWriteMapper.deleteCheckIssue(checkId, issueId);
		} catch (BusinessException e) {
			logger.error("remove issue failure", e);
		}


	}

	@Override
	public void addIssue(Integer checkId, String issueIds) throws BusinessException {
	    String[] idArr = issueIds.split(",");
	    for (String id : idArr) {
	      Integer issueId = Integer.valueOf(id);
	      this.addIssue(checkId, issueId);
	    }

	}

	@Override
	public void removeIssue(Integer checkId, String issueIds) throws BusinessException {
	    String[] idArr = issueIds.split(",");
	    for (String id : idArr) {
	      Integer issueId = Integer.valueOf(id);
	      this.removeIssue(checkId, issueId);
	    }

	}

	@Override
	public Check copyFromTemplate(Integer checkId) throws BusinessException {
		Check check = new Check();
		Check template = (Check) this.get(checkId);
		if (template != null) {
			check = this.buildCheck(template);
			this.insert(check);
			this.buildCheckIssue(check.getId(), template.getId());
		}
		return check;
	}

	private Check buildCheck(Check template) {
		Check check = new Check();
		check.setDescription(template.getDescription());
		check.setName(template.getName());
		check.setSerialNum(template.getSerialNum());
		check.setTemplate(false);
		return check;
	}

	private void buildCheckIssue(Integer checkId, Integer templateId) throws BusinessException {
		List<Issue> issues = issueServiceImpl.getByCheckId(templateId);
		if (issues != null && issues.size() > 0) {
			for (Issue issue : issues) {
				if (issue != null) {
					this.addIssue(checkId, issue.getId());
				}
			}
		}
	}

	@Override
	public void batchAddIssue(Integer checkId, List<Issue> newIssue) throws BusinessException {
		for (Issue issue : newIssue) {
			if (StringUtils.isBlank(issue.getSerialNum())) {
				issue.setSerialNum(System.currentTimeMillis() + "");
			}
			Integer issueId = issueServiceImpl.insert(issue);
			checkWriteMapper.insertCheckIssue(checkId, issueId);
		}
	}

}
